﻿using System.Net;
using System.Net.Sockets;

using GCC.Container.Abstracts;

using static GCC.Container.Comm.Modbus.TCPVersion.ModbusTcpPackage;

namespace GCC.Container.Comm.Modbus.TCPVersion
{
    public class Client : AbsCommTcpClient<ModbusTcpPackage>
    {
        /// <summary>
        /// 当前报文序号
        /// </summary>
        private ushort _seq = 0;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="targetIp">目标IP</param>
        /// <param name="logger">日志</param>
        /// <param name="name">名称</param>
        /// <param name="localInfo">本地地址信息</param>
        public Client(IPEndPoint targetIp, AbsGCCLogger logger, string name, IPEndPoint? localInfo) : base(targetIp, logger, name, localInfo)
        {
            _flagSize = 0;
            _headSize = 8;
        }

        public Client(IPEndPoint targetIp, AbsGCCLogger logger, string name, Socket socket) : base(targetIp, logger, name, socket)
        {
            _flagSize = 0;
            _headSize = 8;
        }

        /// <summary>
        /// 检查flag
        /// </summary> 
        /// <returns></returns>
        protected override bool CheckFlag(in Memory<byte> flagBuffer)
        {
            return true;
        }

        /// <summary>
        /// 检查头
        /// </summary> 
        /// <returns></returns>
        protected override bool CheckHeader(in Memory<byte>? _, in Memory<byte> headBuffer, out int bodyLength)
        {
            bodyLength = BitConverter.ToUInt16(headBuffer.Span[4..6].ToArray().Reverse().ToArray()) - 2;
            return true;
        }

        /// <summary>
        /// 处理数据
        /// </summary> 
        /// <returns></returns>
        protected override ModbusTcpPackage HandleData(in Memory<byte>? _, in Memory<byte> headBuffer, in Memory<byte> bodyBuffer)
        {
            var res = new ModbusTcpPackage()
            {
                Data = new byte[bodyBuffer.Length],
                DeviceIndex = headBuffer.Span[6],
                Feature = (ModbusTcpFeatureEnum)headBuffer.Span[7]
            };
            bodyBuffer.CopyTo(res.Data);
            return res;
        }

        protected override int GetBodyLengh(ModbusTcpPackage data)
        {
            if (data.Data is null)
            {
                return 0;
            }
            return data.Data.Length;
        }


        protected override void PutFlag(Memory<byte> flagBuffer)
        {

        }

        protected override void PutHeader(in Memory<byte>? _, Memory<byte> headBuffer, in ModbusTcpPackage data)
        {
            lock (this)
            {

                BitConverter.GetBytes(_seq).Reverse().ToArray().CopyTo(headBuffer);
                _seq++;
            }
            BitConverter.GetBytes((ushort)(GetBodyLengh(data) + 2)).Reverse().ToArray().CopyTo(headBuffer[4..]);
            headBuffer.Span[6] = data.DeviceIndex;
            headBuffer.Span[7] = (byte)data.Feature;
        }


        protected override void PutData(in Memory<byte>? _, in Memory<byte> __, Memory<byte> bodyBuffer, in ModbusTcpPackage data)
        {
            data.Data.CopyTo(bodyBuffer);
        }
    }
}
